#ifndef COMMAND_HPP
#define COMMAND_HPP

#include <iostream>
#include <vector>
#include "Equipment.hpp"

class Command
{
public:
    // 执行
    virtual void Execute() = 0;
    // 撤销(回滚)
    virtual void Undo() = 0;

private:
};

// 空命令
class VoidCommand : public Command
{
public:
    void Execute() override{};
    void Undo() override{};

private:
};

// 开灯命令
class LightOnCommand : public Command
{
public:
    LightOnCommand()
        : _light(nullptr)
    {
    }

    void SetLight(Light *light)
    {
        _light = light;
    }

    void Execute() override
    {
        if (_light != nullptr)
            _light->On();
    }

    void Undo()
    {
        if (_light != nullptr)
            _light->Off();
    }

private:
    Light *_light;
};

// 关灯命令
class LightOffCommand : public Command
{
public:
    LightOffCommand()
        : _light(nullptr)
    {
    }

    void SetLight(Light *light)
    {
        _light = light;
    }

    void Execute() override
    {
        if (_light != nullptr)
            _light->Off();
    }

    void Undo() override
    {
        if (_light != nullptr)
            _light->On();
    }

private:
    Light *_light;
};

// 开门命令
class DoorOpenCommand : public Command
{
public:
    DoorOpenCommand()
        : _door(nullptr)
    {
    }

    void SetDoor(Door *door)
    {
        _door = door;
    }

    void Execute() override
    {
        _door->Open();
    }

    void Undo() override
    {
        _door->Close();
    }

private:
    Door *_door;
};

// 关门命令
class DoorCloseCommand : public Command
{
public:
    DoorCloseCommand()
        : _door(nullptr)
    {
    }

    void SetDoor(Door *door)
    {
        _door = door;
    }

    void Execute() override
    {
        _door->Close();
    }

    void Undo() override
    {
        _door->Open();
    }

private:
    Door *_door;
};

// 高档位风扇
class CeilingFanHighCommand : public Command
{
    // 枚举风速
public:
    CeilingFanHighCommand()
        : _fan(nullptr)
    {
        _prevSpeed = CeilingFan::OFF;
    }

    void SetFan(Fan *fan)
    {
        _fan = fan;
        _prevSpeed = _fan->GetSpeed();
    }

    void Execute() override
    {
        // 应该获得调整前的风速
        _prevSpeed = _fan->GetSpeed();
        _fan->High();
    }

    void Undo() override
    {
        std::cout << _prevSpeed << std::endl;
        if (_prevSpeed == CeilingFan::HIGH)
        {
            _fan->High();
        }
        else if (_prevSpeed == CeilingFan::MEDIUM)
        {
            _fan->Medium();
        }
        else if (_prevSpeed == CeilingFan::LOW)
        {
            _fan->Low();
        }
        else if(_prevSpeed == CeilingFan::OFF)
        {
            _fan->Off();
        }
    }

private:
    Fan *_fan;
    unsigned long _prevSpeed;
};

// 中档位风扇
class CeilingFanMediumCommand : public Command
{
public:
    CeilingFanMediumCommand()
        : _fan(nullptr)
    {
        _prevSpeed = CeilingFan::OFF;
    }

    void SetFan(Fan *fan)
    {
        _fan = fan;
        _prevSpeed = _fan->GetSpeed();
    }

    void Execute()
    {
        _prevSpeed = _fan->GetSpeed();
        _fan->Medium();
    }

    void Undo() override
    {
        if (_prevSpeed == CeilingFan::HIGH)
        {
            _fan->High();
        }
        else if (_prevSpeed == CeilingFan::MEDIUM)
        {
            _fan->Medium();
        }
        else if (_prevSpeed == CeilingFan::LOW)
        {
            _fan->Low();
        }
        else
        {
            _fan->Off();
        }
    }

private:
    Fan *_fan;
    unsigned int _prevSpeed;
};

// 低档位风扇
class CeilingFanLowCommand : public Command
{
public:
    CeilingFanLowCommand()
        : _fan(nullptr)
    {
        _prevSpeed = CeilingFan::OFF;
    }

    void SetFan(Fan *fan)
    {
        _fan = fan;
        _prevSpeed = _fan->GetSpeed();
    }

    void Execute() override
    {
        _prevSpeed = _fan->GetSpeed();
        _fan->Low();
    }

    void Undo() override
    {
        if (_prevSpeed == CeilingFan::HIGH)
        {
            _fan->High();
        }
        else if (_prevSpeed == CeilingFan::MEDIUM)
        {
            _fan->Medium();
        }
        else if (_prevSpeed == CeilingFan::LOW)
        {
            _fan->Low();
        }
        else
        {
            _fan->Off();
        }
    }

private:
    Fan *_fan;
    unsigned int _prevSpeed;
};

class CeilingFanOffCommand : public Command
{
public:
    CeilingFanOffCommand()
        : _fan(nullptr)
    {
        _prevSpeed = CeilingFan::OFF;
    }

    void SetFan(Fan *fan)
    {
        _fan = fan;
        _prevSpeed = _fan->GetSpeed();
    }

    void Execute() override
    {
        _fan->Off();
        _prevSpeed = CeilingFan::OFF;
    }

    void Undo() override
    {
        _prevSpeed = _fan->GetSpeed();
        if (_prevSpeed == CeilingFan::HIGH)
        {
            _fan->High();
        }
        else if (_prevSpeed == CeilingFan::MEDIUM)
        {
            _fan->Medium();
        }
        else if (_prevSpeed == CeilingFan::LOW)
        {
            _fan->Low();
        }
        else
        {
            _fan->Off();
        }
    }

private:
    Fan *_fan;
    unsigned int _prevSpeed;
};

// 抽象音响命令类
class StereoCommand : public Command
{
public:
    StereoCommand()
        : _stereo(nullptr)
    {
    }

    void SetStereo(Stereo *stereo)
    {
        _stereo = stereo;
    }

    void Undo()
    {
        if (_prevSet == Stereo::ON)
        {
            _stereo->On();
        }
        else if (_prevSet == Stereo::OFF)
        {
            _stereo->Off();
        }
        else if (_prevSet == Stereo::RADIO)
        {
            _stereo->SetRadio();
        }
        else if (_prevSet == Stereo::DVD)
        {
            _stereo->SetDvd();
        }
        else if (_prevSet == Stereo::VOLUME)
        {
            _stereo->SetVolume();
        }
        else 
        {
            _stereo->SetCd();
        }
    }

protected:
    Stereo *_stereo;
    unsigned int _prevSet;
};

// 打开音响
class StereoOnCommand : public StereoCommand
{
public:
    StereoOnCommand()
    {
    }

    void Execute() override
    {
        _prevSet = _stereo->GetPrevSet();
        _stereo->On();
    }

private:
};

// 关闭音响
class StereoOffCommand : public StereoCommand
{
public:
    StereoOffCommand()
    {
    }

    void Execute()
    {
        _prevSet = _stereo->GetPrevSet();
        _stereo->Off();
    }

private:
};

// 播放音乐
class StereoRadioCommand : public StereoCommand
{
public:
    StereoRadioCommand()
    {
    }

    void Execute()
    {
        _prevSet = _stereo->GetPrevSet();
        _stereo->SetRadio();
    }

private:
};

// 播放Dvd
class StereoDvdCommand : public StereoCommand
{
public:
    StereoDvdCommand()
    {
    }

    void Execute()
    {
        _prevSet = _stereo->GetPrevSet();
        _stereo->SetDvd();
    }

private:
};

// 播放音频
class StereoVolumCommand : public StereoCommand
{
public:
    StereoVolumCommand()
    {
    }

    void Execute()
    {
        _prevSet = _stereo->GetPrevSet();
        _stereo->SetVolume();
    }

private:
};

// 播放Cd
class StereoCdCommand : public StereoCommand
{
public:
    StereoCdCommand()
    {
    }

    void Execute()
    {
        _prevSet = _stereo->GetPrevSet();
        _stereo->SetCd();
    }
    
private:
};

// 设置一个综合Party指令
class MacroCommand :public Command
{
public:
    MacroCommand(unsigned int num = 7)
        :_num(num)
    {
        for(int i = 0; i < _num; i++)
        {
            _party.push_back(nullptr);
        }
    }

    // 设置
    void SetPartyCommand(unsigned int num, const std::vector<Command*>& party)
    {
        for(unsigned int i = 0; i < num; i++)
        {
            _party[i] = party[i];
        }
    }

    // 执行
    void Execute() override
    {
        for(int i = 0; i < _party.size(); i++)
        {
            if(_party[i] != nullptr)
                _party[i]->Execute();
        }
    }

    // 撤销
    void Undo()
    {
        for(Command* ptr : _party)
        {
            if(ptr != nullptr)
                ptr->Undo();
        }
    }

    // 清空
    void ClearCommands()
    {
        _party.clear();
    }

private:
    std::vector<Command*> _party;
    const unsigned int _num;
};
#endif
